package com.geek.log4jcontrol.core;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Map.Entry;

import com.geek.log4jcontrol.commons.ConfigConstants;
import com.geek.log4jcontrol.commons.FinalConstants;

/**
 * @package com.geek.log4jcontrol.core
 * @description Log4jControl本身的初始化配置
 * @author Goliath
 * @createTime 2012-8-3 上午09:54:50
 * @modifyTime
 */
public class ConfigLoader {

	private ConfigLoader() {

	}

	private static ConfigLoader configLoader = new ConfigLoader();

	public static ConfigLoader getInstance() {
		return configLoader;
	}

	/**
	 * @package com.geek.log4jcontrol.core
	 * @description 根据参数类型进行不同价加载动作
	 * @param configParam 配置参数
	 * @returnType void
	 * @author Goliath
	 * @createTime 2012-8-3 下午03:41:44
	 * @modifyTime
	 */
	public void doConfigure(Object configParam) {
		if (configParam instanceof String) {
			configure((String) configParam);
		} else if (configParam instanceof Properties) {
			configure((Properties) configParam);
		} else if (configParam instanceof URL) {
			configure((URL) configParam);
		}
	}

	/**
	 * @package com.geek.log4jcontrol.core
	 * @description 通过配置文件名加载Log4jControl本身的配置
	 * @param configFilename
	 * @returnType void
	 * @author Goliath
	 * @createTime 2012-8-3 上午10:41:45
	 * @modifyTime
	 */
	private void configure(String configFilename) {
		Properties props = new Properties();
		try {
			FileInputStream istream = new FileInputStream(configFilename);
			props.load(istream);
			istream.close();
		} catch (IOException e) {
			System.out.println("Could not read configuration file [" + configFilename + "].");
			props = getDefaultConfig();
			System.out.println("Configuration file load default [" + FinalConstants.CONFIGFILE_DEFAULT + "].");
		}
		// If we reach here, then the config file is alright.
		configure(props);
	}

	/**
	 * @package com.geek.log4jcontrol.core
	 * @description 获取默认的配置
	 * @return 默认的Log4jControl配置
	 * @returnType Properties
	 * @author Goliath
	 * @createTime 2012-8-3 上午10:42:19
	 * @modifyTime
	 */
	public Properties getDefaultConfig() {

		Properties props = new Properties();
		try {
			InputStream istream = this.getClass().getResourceAsStream("/" + FinalConstants.CONFIGFILE_DEFAULT);
			props.load(istream);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return props;
	}

	/**
	 * @package com.geek.log4jcontrol.core
	 * @description 通过URL加载Log4jControl本身的配置
	 * @param configURL
	 * @returnType void
	 * @author Goliath
	 * @createTime 2012-8-3 上午10:42:45
	 * @modifyTime
	 */
	private void configure(URL configURL) {
		Properties props = new Properties();
		System.out.println("Reading configuration from URL " + configURL);
		try {
			props.load(configURL.openStream());
		} catch (IOException e) {
			System.out.println("Could not read configuration file from URL [" + configURL + "].");
			System.out.println("Ignoring configuration file [" + configURL + "].");
			props = getDefaultConfig();
			System.out.println("Configuration file load default [" + FinalConstants.CONFIGFILE_DEFAULT + "].");
		}
		// If we reach here, then the config by url is alright.
		configure(props);
	}

	/**
	 * @package com.geek.log4jcontrol.core
	 * @description 通过Properties加载Log4jControl本身的配置
	 * @param properties Log4jControl本身的配置
	 * @returnType void
	 * @author Goliath
	 * @createTime 2012-8-3 上午10:43:05
	 * @modifyTime
	 */
	@SuppressWarnings("unchecked")
	private void configure(Properties properties) {
		Iterator it = properties.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry<String, String> entry = (Entry<String, String>) it.next();
			String configName = entry.getKey();
			String configValue = entry.getValue();
			System.out.println("---- KEY:" + configName + " VALUE:" + configValue + " ----");
			if (!"".equals(configName)) {
				String paramName = getParamName(configName);
				flashConfig(paramName, configValue, ConfigConstants.class);
			}

		}
	}

	/**
	 * @package com.geek.log4jcontrol.core
	 * @description 配置文件的key转换为配置的key， "."号转换为"_"并大写所有字母
	 * @param configName 配置参数名
	 * @return 转换后的参数名
	 * @returnType String
	 * @author Goliath
	 * @createTime 2012-8-3 上午10:43:35
	 * @modifyTime
	 */
	private String getParamName(String configName) {
		String[] paramStrArr = configName.split("\\.");
		String paramName = "";
		for (String paramStr : paramStrArr) {
			paramName += paramStr + "_";
		}
		return paramName.substring(0, paramName.length() - 1).toUpperCase();
	}

	/**
	 * @package com.geek.log4jcontrol.core
	 * @description 刷新配置，非基本类型走自定义的配置方法加载
	 * @param paramName
	 * @param configValue
	 * @param clazz
	 * @returnType void
	 * @author Goliath
	 * @createTime 2012-8-3 上午10:44:58
	 * @modifyTime
	 */
	@SuppressWarnings("unchecked")
	private void flashConfig(String paramName, String configValue, Class clazz) {
		try {
			Field oField = clazz.getField(paramName);
			if (oField != null) {
				// 基本类型读取
				if (oField.getType() == byte.class) {// 域为Integer类型
					byte value = Byte.valueOf(configValue);
					oField.set(null, value);
				} else if (oField.getType() == short.class) {// 域为Integer类型
					Short value = Short.valueOf(configValue);
					oField.set(null, value);
				} else if (oField.getType() == int.class) {// 域为Integer类型
					int value = Integer.valueOf(configValue);
					oField.set(null, value);
				} else if (oField.getType() == long.class) {// 域为Double类型
					long value = Long.valueOf(configValue);
					oField.set(null, value);
				} else if (oField.getType() == float.class) {// 域为Double类型
					float value = Float.valueOf(configValue);
					oField.set(null, value);
				} else if (oField.getType() == double.class) {// 域为Double类型
					double value = Double.valueOf(configValue);
					oField.set(null, value);
				} else if (oField.getType() == boolean.class) {// 域为Double类型
					boolean value = Boolean.valueOf(configValue);
					oField.set(null, value);
				} else if (oField.getType() == char.class) {// 域为Double类型
					if (configValue.length() >= 1) {
						char value = configValue.charAt(0);
						oField.set(null, value);
					}
				} else {// 域不为基本类型
					// String 类型直接赋值
					if (oField.getType() == String.class) {// 域为String类型
						oField.set(null, configValue);
					} else {
						// 调用特殊类型的初始化方法
						String methodName = FinalConstants.INIT + paramName.toUpperCase();
						Method method = clazz.getMethod(methodName, configValue.getClass());
						method.invoke(null, configValue);
					}
				}
			}
		} catch (NumberFormatException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}
}
